package cn.iocoder.yudao.module.lfd.service.number;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.lfd.dal.dataobject.number.NumberDO;
import cn.iocoder.yudao.module.lfd.dal.mysql.number.NumberMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.sql.SQLIntegrityConstraintViolationException;
import java.time.LocalDate;

@Service
@Validated
public class NumberServiceImpl implements NumberService {
    @Resource
    private NumberMapper numberMapper;

    @Override
    @Transactional(isolation=Isolation.READ_COMMITTED)
    public String createNumber(String code,Long barberId, LocalDate date) {
        Long seqNumber = generateNumber(barberId, date);
        return code+String.format("%03d", seqNumber);
    }

    private Long generateNumber(Long barberId, LocalDate date) {
        NumberDO numberDO = numberMapper.selectOne("barber_id", barberId, "seq_date", date);
        if (numberDO != null) {
            return updated(numberDO);
        }
        numberDO = new NumberDO().setSeqNumber(1L).setSeqDate(LocalDate.now()).setBarberId(barberId).setVersion(IdUtil.fastSimpleUUID());
        try {
            numberMapper.insert(numberDO);
            return numberDO.getSeqNumber();
        } catch (Exception e) {
            return IdUtil.getSnowflakeNextId();
        }
    }

    private Long updated(NumberDO numberDO) {
        QueryWrapper<NumberDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", numberDO.getId());
        queryWrapper.eq("version", numberDO.getVersion());
        numberDO.setSeqNumber(numberDO.getSeqNumber() + 1L).setVersion(IdUtil.fastSimpleUUID());
        int update = numberMapper.update(numberDO, queryWrapper);
        if (update == 0) {
            return IdUtil.getSnowflakeNextId();
        }
        return numberDO.getSeqNumber();
    }
}
